Jerry's Blogs

Monday, October 29, 2007

On Yumify: Places

I woke up this morning and had a pretty clear chain of thought for implementing Places. These are some notes and arguments I came up with.

Issues

  1. Place object is really a reference to a Yelp object returned by Ruby Yelp API
  2. A call needs to be made every time a Place object is created

Peter was absolutely right when he came up with that first statement. It doesn't make sense to use ActiveRecord for an object that will have a single field. It might be convenient because of the methods ActiveRecord provides, but it's kind of cheating... The fix was to simply use a normal object that wraps around a returned Yelp object.

The basic wrapper isn't good enough because it could become stale, and also because a call would need to be made to every Yelp object. Calls would need to be made for the initial query, and there may be repeated calls for each individual result. There would also be calls for each 'favorited' place. The network I/O would kill us.

The solution I came up with is to abstract one more level from the Yelp Ruby API, and create a class called YelpProxy. YelpProxy makes search queries on your behalf, caches the most used results, and returns pre-wrapped Place objects. Here are the pros I came up with this design:

  • A single Yelp::Client can be reused for multiple searches
  • Same benefit of no duplicate data with Yelp.
  • Caching can be implemented by retaining the most frequently fetched. This leads to fewer API calls, and instant access to Place objects.
  • Every fetch can timestamp the Place created. Places can be kept as fresh as needed.
  • All other classes can use Place objects without worrying about constructing it.

There are two places where it made sense to implement these features. The way I have it currently is to have a separate YelpProxy class in the lib/ directory. I like it this way for now because it's easy to understand and edit. The other way is to add caching as an option directly into the Ruby Yelp API. This method might make more sense later and could be helpful to others if we submitted it upstream.

Technical Notes

  • Cache can be a Hash of Place objects with a maximum size. There'd be separate structure (min heap) to keep track of the least used Place.
  • When a request comes into the YelpProxy, check the cache to see if the Place exists. If so, check to see if it's fresh. If so, return that Place, and increment it's 'hotness' in the cache.
  • If any of the above was 'no', then fetch a Yelp object, wrap it in a Place object, and stick it in the cache. Eject the coldest object if the cache is full
  • extra metadata about how many times a Place is fetched. Can be correlated to other factors.

This buys you constant access to the most used Places, and saves a ton of API calls. In fact, since the API is limited to 10,000 calls/day, setting a large size cache would make our site scale much better. For development, a cache size of 50 or so would work.

Labels:

0 Comments:

Post a Comment

Subscribe to Post Comments [Atom]

<< Home